using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using SBPweb.Presentation.Windows.Forms.Controls;
using SBPweb.Contracts.WebBrowser;
using SBPweb.Modules.Modularity;
using SHDocVw;
using SBPweb.Localization;
using SBPweb.Contracts.Implementation;
using SBPweb.Contracts;
using System.Runtime.InteropServices;

namespace SBPweb.Modules.WebBrowser
{
	public partial class WebBrowserControl : DockingUserControl, IWebBrowserService
	{
		#region Private members

		private Guid cmdGuid = new Guid("ED016940-BD5B-11CF-BA4E-00C04FD70816");
		private Dictionary<string, DateTime> mVisitedPages = new Dictionary<string, DateTime>();
		private TD.SandDock.TabbedDocument lastActivatedDocument;
		private AxSHDocVw.AxWebBrowser _ActiveWebBrowser;
		private bool _FirstShown;
		private bool mAskBeforePrint = true;
		private FavoritesControl mFavoritesControl;
		private IModule mParentModule;

		private bool IsPrinterEnabled
		{
			get
			{
				if (_ActiveWebBrowser == null)
				{
					return false;
				}
				int response = (int)_ActiveWebBrowser.QueryStatusWB(SHDocVw.OLECMDID.OLECMDID_PRINT);
				return (response & (int)SHDocVw.OLECMDF.OLECMDF_ENABLED) != 0 ? true : false;
			}
		}

		#endregion

		#region Constructor logic

		public WebBrowserControl(IModule parentModule)
			: base(parentModule)
		{
			mParentModule = parentModule;

            MinimumSize = new Size(800, 600);

			InitializeComponent();
			
			LocalizationExtender.OnInvalidatedControls += new EventHandler(LocalizationExtender_OnInvalidatedControls);

            sandDockManager.OwnerForm = parentModule.Host as Form;

            this.Closing += new EventHandler(WebBrowserControl_Closing);
		}


		#endregion

		#region Sanddock event handlers

		private void sandDockManager_DockControlActivated(object sender, TD.SandDock.DockControlEventArgs e)
		{
			//lastActivatedDocument = e.DockControl as TD.SandDock.TabbedDocument;
            //SetActiveWebBrowser();
		}

		private void sandDockManager_DockControlClosing(object sender, TD.SandDock.DockControlClosingEventArgs e)
		{
			if (documentContainer.Controls.Count < 2)
			{
				CreateNewWebBrowser();
			}
		}

		private void sandDockManager_ActiveTabbedDocumentChanged(object sender, System.EventArgs e)
		{
            if (sandDockManager.ActiveTabbedDocument != null)
            {
                lastActivatedDocument = sandDockManager.ActiveTabbedDocument as TD.SandDock.TabbedDocument;
                SetActiveWebBrowser();
            }
            else
            {
                new _hackActivatehandler(_hackActivate).BeginInvoke(null, null);
                //sandDockManager.Documents[0].Activate();
            }
		}

        private delegate void _hackActivatehandler();
        private void _hackActivate()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new _hackActivatehandler(_hackActivate));
                return;
            }
            try
            {
				(documentContainer.Controls[0] as TD.SandDock.TabbedDocument).Open(TD.SandDock.WindowOpenMethod.OnScreenActivate);
            }
            catch { }
        }

		#endregion

		#region IWebBrowserService Members

		public void OpenURL(string url, bool newTab)
		{
            if (ParentForm != null)
                ParentForm.Visible = true;

			IsVisible = true;
            
			if (newTab)
			{
				WebBrowserNewTab(url);
			}
			else
			{
				WebBrowserGo(url);
			}
		}

		#endregion

		#region IService Members

		public IModule Module
		{
			get { return ParentModule; }
		}

		#endregion

		#region Persistency

		internal void SavePersistence(PersistencyDictionary state)
		{
			int addedItems = 0;
			foreach (string key in mVisitedPages.Keys)
			{
				TimeSpan ts = DateTime.Now - mVisitedPages[key];
				if (ts.Days > 7)
				{
					continue;
				}
				addedItems++;
				state.SetString("WebPage" + addedItems.ToString(), key);
				state.SetString("LastVisit" + addedItems.ToString(), mVisitedPages[key].ToString());
			}
			state.SetInt("ItemCount", addedItems);

			//
			// Saving the size of the ToolStrips
			//
            //state.SetInt("tsNavigationWidth", tsNavigation.Size.Width);
            //state.SetInt("tsNavigationHeight", tsNavigation.Size.Height);

            //state.SetInt("tsActionsWidth", tsActions.Size.Width);
            //state.SetInt("tsActionsHeight", tsActions.Size.Height);
		}

		internal void LoadPersistence(PersistencyDictionary state)
		{
			mVisitedPages = new Dictionary<string, DateTime>();
			int items = state.GetInt("ItemCount", 0);
			for (int i = 1; i <= items; i++)
			{
				string webPage = state.GetString("WebPage" + i.ToString(), string.Empty);
				DateTime lastVisitedTime = DateTime.Now;
				if (DateTime.TryParse(state.GetString("LastVisit" + i.ToString(), string.Empty), out lastVisitedTime) && !string.IsNullOrEmpty(webPage))
				{
					if (!mVisitedPages.ContainsKey(webPage))
					{
						mVisitedPages.Add(webPage, lastVisitedTime);
					}
				}
			}

			//
			// Loading the size of the ToolStrips
			//
            ItemResize(tsNavigation, MenuToolStrip.GetSizeByToolStripSize(ToolStripSizes.Medium));
            ItemResize(tsActions, MenuToolStrip.GetSizeByToolStripSize(ToolStripSizes.Medium));
		}

		#endregion

		#region Event handlers

		private void LocalizationExtender_OnInvalidatedControls(object sender, EventArgs e)
		{
			foreach (object o in tsActions.Items)
			{
				if (o is ToolStripButton)
				{
					ToolStripButton c = o as ToolStripButton;
					c.Text = LocalizationExtender.GetString(this, c.Name + ".Text");
				}
			}
			foreach (object o in tsNavigation.Items)
			{
				if (o is ToolStripButton)
				{
					ToolStripButton c = o as ToolStripButton;
					c.Text = LocalizationExtender.GetString(this, c.Name + ".Text");
				}
			}
			foreach (object o in msMenu.Items)
			{
				if (o is ToolStripMenuItem)
				{
					ToolStripMenuItem c = o as ToolStripMenuItem;
					c.Text = LocalizationExtender.GetString(this, c.Name + ".Text");
					foreach (object o2 in c.DropDownItems)
					{
						if (o2 is ToolStripDropDownItem)
						{
							ToolStripDropDownItem c2 = o2 as ToolStripDropDownItem;
							c2.Text = LocalizationExtender.GetString(this, c2.Name + ".Text");
						}
					}
				}
			}
		}

        void WebBrowserControl_Closing(object sender, EventArgs e)
        {
            while (documentContainer.Controls.Count > 1)
            {
                WebBrowserCloseTab(documentContainer.Controls[0] as TD.SandDock.TabbedDocument);
            }

            //close the last one :)
            WebBrowserCloseTab(documentContainer.Controls[0] as TD.SandDock.TabbedDocument);
        }

		private void cbAddress_DropDown(object sender, EventArgs e)
		{
			cbAddress.BeginUpdate();
			cbAddress.Items.Clear();
			foreach (string key in mVisitedPages.Keys)
			{
				cbAddress.Items.Add(key);
			}
			cbAddress.EndUpdate();
		}

		private void cbAddress_KeyDown(object sender, KeyEventArgs e)
		{
			if (e.KeyCode == Keys.Return)
			{
				WebBrowserGo();
			}
		}

		private void WebBrowserControl_Load(object sender, System.EventArgs e)
		{
			if (_FirstShown == false)
			{
				cbAddress.Focus();
				cbAddress.Text = "about:blank";
				_FirstShown = true;
				CreateNewWebBrowser();
				SetActiveWebBrowser();
				WebBrowserGoHome();
			}
		}

		private void WebBrowserControl_Resize(object sender, EventArgs e)
		{
			toolStripStatusLabel.Width = this.ClientRectangle.Width - toolStripProgressBar.Width - 10;
		}

		private void ItemResize(object sender, int size)
		{
			ToolStrip ts = sender as ToolStrip;
			if (ts == null)
			{
				return;
			}

			switch (ts.Name)
			{
				case "tsNavigation":
					tsbBack.Image = Properties.Resources.Back_32x32.GetThumbnailImage(size, size, null, IntPtr.Zero);
					tsbForward.Image = Properties.Resources.Forward_32x32.GetThumbnailImage(size, size, null, IntPtr.Zero);
					tsbRefresh.Image = Properties.Resources.Refresh_32x32.GetThumbnailImage(size, size, null, IntPtr.Zero);
					tsbStop.Image = Properties.Resources.Stop_32x32.GetThumbnailImage(size, size, null, IntPtr.Zero);
					tsbHome.Image = Properties.Resources.Home_32x32.GetThumbnailImage(size, size, null, IntPtr.Zero);
					tsbSearch.Image = Properties.Resources.Search_32x32.GetThumbnailImage(size, size, null, IntPtr.Zero);
					tsbFavorites.Image = Properties.Resources.Favorite_32x32.GetThumbnailImage(size, size, null, IntPtr.Zero);
					break;
				case "tsActions":
					tsbNewTab.Image = Properties.Resources.NewTab_32x32.GetThumbnailImage(size, size, null, IntPtr.Zero);
					tsbCloseTab.Image = Properties.Resources.CloseTab_32x32.GetThumbnailImage(size, size, null, IntPtr.Zero);
					tsbOpen.Image = Properties.Resources.Open_32x32.GetThumbnailImage(size, size, null, IntPtr.Zero);
					tsbSave.Image = Properties.Resources.Save_32x32.GetThumbnailImage(size, size, null, IntPtr.Zero);
					tsbPrint.Image = Properties.Resources.Print_32x32.GetThumbnailImage(size, size, null, IntPtr.Zero);
					tsbFind.Image = Properties.Resources.Find_32x32.GetThumbnailImage(size, size, null, IntPtr.Zero);
					break;
				case "msMenu":
					break;
			}
		}

		#region aXWebBrowser event handlers

		private void axWebBrowser_BeforeNavigate2(object sender, AxSHDocVw.DWebBrowserEvents2_BeforeNavigate2Event e)
		{
			HE_WebBrowserTag _HE_WebBrowserTag = (HE_WebBrowserTag)_ActiveWebBrowser.Tag;
			if (_HE_WebBrowserTag._TabIndex != documentContainer.Controls.IndexOf(lastActivatedDocument))
			{
				return;
			}

			lastActivatedDocument.Text = e.uRL.ToString();

			tsbStop.Enabled = true;
			//string loadingString = LocalizationExtender.GetString("BeforeNavigateLoadingString");
			//toolStripStatusLabel.Text = loadingString == null ? "Loading..." : loadingString;

			if (_HE_WebBrowserTag._TabIndex == documentContainer.Controls.IndexOf(lastActivatedDocument))
			{
				tsbForward.Enabled = _HE_WebBrowserTag._CanForward;
				tsmiForward.Enabled = _HE_WebBrowserTag._CanForward;
				tsbBack.Enabled = _HE_WebBrowserTag._CanBack;
				tsmiBack.Enabled = _HE_WebBrowserTag._CanBack;
			}

			ParentModule.Host.LogManager.WriteVerbose(this, "Start to navigate to " + e.uRL, "WebBrowser");
		}

		private void axWebBrowser_CommandStateChange(object sender, AxSHDocVw.DWebBrowserEvents2_CommandStateChangeEvent e)
		{
			AxSHDocVw.AxWebBrowser _AxWebBrowser = (AxSHDocVw.AxWebBrowser)sender;
			HE_WebBrowserTag _HE_WebBrowserTag;
			_HE_WebBrowserTag = (HE_WebBrowserTag)_AxWebBrowser.Tag;

			switch (e.command)
			{
				case ((int)CommandStateChangeConstants.CSC_NAVIGATEFORWARD):
					_HE_WebBrowserTag._CanForward = e.enable;
					break;

				case ((int)CommandStateChangeConstants.CSC_NAVIGATEBACK):
					_HE_WebBrowserTag._CanBack = e.enable;
					break;

				default:
					break;
			}
			_AxWebBrowser.Tag = _HE_WebBrowserTag;

			if (_HE_WebBrowserTag._TabIndex == documentContainer.Controls.IndexOf(lastActivatedDocument))
			{
				tsbForward.Enabled = _HE_WebBrowserTag._CanForward;
				tsmiForward.Enabled = _HE_WebBrowserTag._CanForward;
				tsbBack.Enabled = _HE_WebBrowserTag._CanBack;
				tsmiBack.Enabled = _HE_WebBrowserTag._CanBack;
			}
		}

		private void axWebBrowser_DocumentComplete(object sender, AxSHDocVw.DWebBrowserEvents2_DocumentCompleteEvent e)
		{
			if (_ActiveWebBrowser.ReadyState == SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE)
			{
				HE_WebBrowserTag _HE_WebBrowserTag = (HE_WebBrowserTag)_ActiveWebBrowser.Tag;
				if (_HE_WebBrowserTag._TabIndex == documentContainer.Controls.IndexOf(lastActivatedDocument))
				{
					//toolStripStatusLabel.Text = _ActiveWebBrowser.LocationURL;
					cbAddress.Text = _ActiveWebBrowser.LocationURL;
					lastActivatedDocument.Text = _ActiveWebBrowser.LocationName;
				}

				toolStripProgressBar.Value = 0;
				toolStripProgressBar.Visible = false;

				tsbPrint.Enabled = IsPrinterEnabled;

				if (_HE_WebBrowserTag._TabIndex == documentContainer.Controls.IndexOf(lastActivatedDocument))
				{
					tsbForward.Enabled = _HE_WebBrowserTag._CanForward;
					tsmiForward.Enabled = _HE_WebBrowserTag._CanForward;
					tsbBack.Enabled = _HE_WebBrowserTag._CanBack;
					tsmiBack.Enabled = _HE_WebBrowserTag._CanBack;
				}

				ParentModule.Host.LogManager.WriteVerbose(this, "Document (" + e.uRL + ") completed.", "WebBrowser");
			}
		}

		private void axWebBrowser_NavigateComplete2(object sender, AxSHDocVw.DWebBrowserEvents2_NavigateComplete2Event e)
		{
			HE_WebBrowserTag _HE_WebBrowserTag = (HE_WebBrowserTag)_ActiveWebBrowser.Tag;
			if (_HE_WebBrowserTag._TabIndex != documentContainer.Controls.IndexOf(lastActivatedDocument))
			{
				return;
			}

			Cursor.Current = Cursors.Default;
			tsbStop.Enabled = false;
			tsbHome.Enabled = true;
			tsbSearch.Enabled = true;
			tsbRefresh.Enabled = true;
			tsbFind.Enabled = true;
			toolStripProgressBar.Value = 0;

			ParentModule.Host.LogManager.WriteVerbose(this, "Navigate to " + e.uRL + " finished.", "WebBrowser");
		}

		private void axWebBrowser_NavigateError(object sender, AxSHDocVw.DWebBrowserEvents2_NavigateErrorEvent e)
		{
			HE_WebBrowserTag _HE_WebBrowserTag = (HE_WebBrowserTag)_ActiveWebBrowser.Tag;
			if (_HE_WebBrowserTag._TabIndex != documentContainer.Controls.IndexOf(lastActivatedDocument))
			{
				return;
			}

			Cursor.Current = Cursors.Default;
			tsbStop.Enabled = false;
			tsbHome.Enabled = true;
			tsbSearch.Enabled = true;
			tsbRefresh.Enabled = true;

			ParentModule.Host.LogManager.WriteVerbose(this, "Navigate error at " + e.uRL + ". " + e.statusCode, "WebBrowser");
		}

		private void axWebBrowser_NewWindow2(object sender, AxSHDocVw.DWebBrowserEvents2_NewWindow2Event e)
		{
			AxSHDocVw.AxWebBrowser _axWebBrowser = CreateNewWebBrowser();
			e.ppDisp = _axWebBrowser.Application;
			_axWebBrowser.RegisterAsBrowser = true;
		}

		private void axWebBrowser_ProgressChange(object sender, AxSHDocVw.DWebBrowserEvents2_ProgressChangeEvent e)
		{
			AxSHDocVw.AxWebBrowser axWebBrowser1 = (AxSHDocVw.AxWebBrowser)sender;
			HE_WebBrowserTag _HE_WebBrowserTag = (HE_WebBrowserTag)axWebBrowser1.Tag;

			if (_HE_WebBrowserTag._TabIndex != documentContainer.Controls.IndexOf(lastActivatedDocument))
			{
				return;
			}

			toolStripProgressBar.Visible = true;
			if ((e.progress > 0) && (e.progressMax > 0))
			{
				toolStripProgressBar.Maximum = e.progressMax;
				toolStripProgressBar.Step = e.progress;
			}
			else if (axWebBrowser1.ReadyState == SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE)
			{
				toolStripProgressBar.Value = 0;
				toolStripProgressBar.Visible = false;
			}
		}

		private void axWebBrowser_StatusTextChange(object sender, AxSHDocVw.DWebBrowserEvents2_StatusTextChangeEvent e)
		{
			AxSHDocVw.AxWebBrowser _AxWebBrowser = (AxSHDocVw.AxWebBrowser)sender;
			HE_WebBrowserTag _HE_WebBrowserTag = (HE_WebBrowserTag)_AxWebBrowser.Tag;
			if (_HE_WebBrowserTag._TabIndex != documentContainer.Controls.IndexOf(lastActivatedDocument))
			{
				return;
			}
			toolStripStatusLabel.Text = e.text;
		}

		private void axWebBrowser_TitleChange(object sender, AxSHDocVw.DWebBrowserEvents2_TitleChangeEvent e)
		{
			AxSHDocVw.AxWebBrowser _AxWebBrowser = (AxSHDocVw.AxWebBrowser)sender;
			HE_WebBrowserTag _HE_WebBrowserTag;
			_HE_WebBrowserTag = (HE_WebBrowserTag)_AxWebBrowser.Tag;
			//TODO: Replace
			//tcTabs.TabPages[_HE_WebBrowserTag._TabIndex].Text = e.text;
		}

		private void axWebBrowser_WindowClosing(object sender, AxSHDocVw.DWebBrowserEvents2_WindowClosingEvent e)
		{
			WebBrowserCloseTab(null);
		}

		#endregion

		#region Click events

		private void tsbNewTab_Click(object sender, EventArgs e)
		{
			WebBrowserNewTab();
		}

		private void tsbCloseTab_Click(object sender, EventArgs e)
		{
			WebBrowserCloseTab(null);
		}

		private void tsbOpen_Click(object sender, EventArgs e)
		{
			WebBrowserOpenFile();
		}

		private void tsbSave_Click(object sender, EventArgs e)
		{
			WebBrowserSaveFile();
		}

		private void tsbPrint_Click(object sender, EventArgs e)
		{
			WebBrowserPrintPage();
		}

		private void tsbBack_Click(object sender, EventArgs e)
		{
			WebBrowserGoBack();
		}

		private void tsbForward_Click(object sender, EventArgs e)
		{
			WebBrowserGoForward();
		}

		private void tsbStop_Click(object sender, EventArgs e)
		{
			WebBrowserStop();
		}

		private void tsbRefresh_Click(object sender, EventArgs e)
		{
			WebBrowserRefresh();
		}

		private void tsbHome_Click(object sender, EventArgs e)
		{
			WebBrowserGoHome();
		}

		private void tsbSearch_Click(object sender, EventArgs e)
		{
			WebBrowserSearch();
		}

		private void tsbFind_Click(object sender, EventArgs e)
		{
			WebBrowserFind();
		}

		private void tsbFavorites_Click(object sender, EventArgs e)
		{
			WebBrowserShowFavorites();
		}

		private void newTabToolStripMenuItem_Click(object sender, EventArgs e)
		{
			WebBrowserNewTab();
		}

		private void closeCurrentTabToolStripMenuItem_Click(object sender, EventArgs e)
		{
			WebBrowserCloseTab(null);
		}

		private void openToolStripMenuItem_Click(object sender, EventArgs e)
		{
			WebBrowserOpenFile();
		}

		private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
		{
			WebBrowserSaveFile();
		}

		private void pageSetupToolStripMenuItem_Click(object sender, EventArgs e)
		{
			WebBrowserPageSetup();
		}

		private void printToolStripMenuItem_Click(object sender, EventArgs e)
		{
			WebBrowserPrint();
		}

		private void printPreviewToolStripMenuItem_Click(object sender, EventArgs e)
		{
			WebBrowserPrintPreview();
		}

		private void propertiesToolStripMenuItem_Click(object sender, EventArgs e)
		{
			WebBrowserProperties();
		}

		private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
		{
			WebBrowserInternetOptions();
		}

		private void cutToolStripMenuItem_Click(object sender, EventArgs e)
		{
			WebBrowserCutClipboard();
		}

		private void copyToolStripMenuItem_Click(object sender, EventArgs e)
		{
			WebBrowserCopyClipboard();
		}

		private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
		{
			WebBrowserPasteClipboard();
		}

		private void selectAllToolStripMenuItem_Click(object sender, EventArgs e)
		{
			WebBrowserSelectAll();
		}

		private void findToolStripMenuItem_Click(object sender, EventArgs e)
		{
			WebBrowserFind();
		}

		private void goBackToolStripMenuItem_Click(object sender, EventArgs e)
		{
			WebBrowserGoBack();
		}

		private void goForwardToolStripMenuItem_Click(object sender, EventArgs e)
		{
			WebBrowserGoForward();
		}

		private void stopToolStripMenuItem_Click(object sender, EventArgs e)
		{
			WebBrowserStop();
		}

		private void refreshToolStripMenuItem_Click(object sender, EventArgs e)
		{
			WebBrowserRefresh();
		}

		private void searchToolStripMenuItem_Click(object sender, EventArgs e)
		{
			WebBrowserSearch();
		}

		private void sourceToolStripMenuItem_Click(object sender, EventArgs e)
		{
			WebBrowserViewSource();
		}

		private void tsmiFavorites_Click(object sender, EventArgs e)
		{
			WebBrowserShowFavorites();
		}

		private void btnGo_Click(object sender, EventArgs e)
		{
			WebBrowserGo();
		}

		#endregion

		#endregion

		#region Private helper methods

		private void WebBrowserGo()
		{
			//toolStripStatusLabel.Text = string.Empty;
			string url = cbAddress.Text;

			WebBrowserGo(url);
		}

		private void WebBrowserGo(string url)
		{
			//toolStripStatusLabel.Text = string.Empty;
			cbAddress.Text = url;
			if (url == "about:blank")
			{
				lastActivatedDocument.Text = "about:blank";
			}

			if (url == "")
			{
				return;
			}
			try
			{
				Cursor.Current = Cursors.WaitCursor;
				Object o = null;
				_ActiveWebBrowser.Navigate(url, ref o, ref o, ref o, ref o);
			}
			finally
			{
				if (mVisitedPages.ContainsKey(url))
				{
					mVisitedPages[url] = DateTime.Now;
				}
				else
				{
					mVisitedPages.Add(url, DateTime.Now);
				}

				Cursor.Current = Cursors.Default;
			}

			ParentModule.Host.LogManager.WriteVerbose(this, "Start to navigate to " + cbAddress.Text, "WebBrowser");
		}

		private void WebBrowserGoHome()
		{
			ParentModule.Host.LogManager.WriteVerbose(this, "Go home.", "WebBrowser");

			_ActiveWebBrowser.GoHome();
		}

		private void WebBrowserGoBack()
		{
			ParentModule.Host.LogManager.WriteVerbose(this, "Go back.", "WebBrowser");

			_ActiveWebBrowser.GoBack();
		}

		private void WebBrowserGoForward()
		{
			ParentModule.Host.LogManager.WriteVerbose(this, "Go forward.", "WebBrowser");

			_ActiveWebBrowser.GoForward();
		}

		private void WebBrowserStop()
		{
			ParentModule.Host.LogManager.WriteVerbose(this, "Stopped.", "WebBrowser");

			_ActiveWebBrowser.Stop();
			//string stoppedString = LocalizationExtender.GetString("StopNavigateString");
			//toolStripStatusLabel.Text = stoppedString == null ? "Stopped" : stoppedString;

			toolStripProgressBar.Value = 0;
			toolStripProgressBar.Visible = false;
		}

		private void WebBrowserRefresh()
		{
			ParentModule.Host.LogManager.WriteVerbose(this, "Refresh.", "WebBrowser");

			object REFRESH_COMPLETELY = 3;
			_ActiveWebBrowser.Refresh2(ref REFRESH_COMPLETELY);
		}

		private void WebBrowserNewTab()
		{
			WebBrowserNewTab("about:blank");
		}

		private void WebBrowserNewTab(string url)
		{
			CreateNewWebBrowser(url);
			cbAddress.Focus();
			cbAddress.Text = url;
		}

		private void WebBrowserCloseTab(TD.SandDock.TabbedDocument td)
		{
			TD.SandDock.TabbedDocument closeable = null;

			if (documentContainer.Controls.Count == 1)
			{
				closeable = lastActivatedDocument;
				CreateNewWebBrowser();
				lastActivatedDocument = closeable;
			}

			if (td == null)
			{
				lastActivatedDocument.Dispose();
			}
			else
			{
				documentContainer.Controls.Remove(td);
				td.Dispose();
			}

			sandDockManager_ActiveTabbedDocumentChanged(this, EventArgs.Empty);
			SetActiveWebBrowser();
		}

		private void WebBrowserFind()
		{
			ParentModule.Host.LogManager.WriteVerbose(this, "Find.", "WebBrowser");

			IOleCommandTarget cmdt = (IOleCommandTarget)GetDocument();
			Object o = new object();

			if (cmdt != null)
			{
				cmdt.Exec(ref cmdGuid, (uint)MiscCommandTarget.Find, (uint)SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, ref o, ref o);
			}
		}

		private void WebBrowserSearch()
		{
			ParentModule.Host.LogManager.WriteVerbose(this, "Search.", "WebBrowser");

			_ActiveWebBrowser.GoSearch();
		}

		private void WebBrowserViewSource()
		{
			ParentModule.Host.LogManager.WriteVerbose(this, "View source.", "WebBrowser");

			IOleCommandTarget cmdt;
			Object o = new object();
			try
			{
				cmdt = (IOleCommandTarget)GetDocument();
				cmdt.Exec(ref cmdGuid, (uint)MiscCommandTarget.ViewSource,
					(uint)SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, ref o, ref o);
			}
			catch (Exception e)
			{
				System.Windows.Forms.MessageBox.Show(e.Message);
			}
		}

		private void WebBrowserInternetOptions()
		{
			ParentModule.Host.LogManager.WriteVerbose(this, "Internet options.", "WebBrowser");

			IOleCommandTarget cmdt;
			Object o = new object();
			try
			{
				cmdt = (IOleCommandTarget)GetDocument();
				if (cmdt != null)
				{
					cmdt.Exec(ref cmdGuid, (uint)MiscCommandTarget.Options,
						(uint)SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, ref o, ref o);
				}
			}
			catch
			{
				// NOTE: Because of the way that this CMDID is handled in Internet Explorer,
				// this catch block will always fire, even though the dialog box
				// and its operations completed successfully. You can suppress this
				// error without causing any damage to your host.
			}
		}

		private void WebBrowserProperties()
		{
			ParentModule.Host.LogManager.WriteVerbose(this, "Properties.", "WebBrowser");

			ExecCommandID(SHDocVw.OLECMDID.OLECMDID_PROPERTIES);
		}

		private void WebBrowserPrintPage()
		{
			ParentModule.Host.LogManager.WriteVerbose(this, "Print page.", "WebBrowser");

			object o = "";
			SHDocVw.OLECMDID Print = SHDocVw.OLECMDID.OLECMDID_PRINT;
			SHDocVw.OLECMDEXECOPT PromptUser = SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_PROMPTUSER;
			SHDocVw.OLECMDEXECOPT DontPromptUser = SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER;

			if (!IsPrinterEnabled) return;

			if (mAskBeforePrint)
			{
				_ActiveWebBrowser.ExecWB(Print, PromptUser, ref o, ref o);
			}
			else
			{
				_ActiveWebBrowser.ExecWB(Print, DontPromptUser, ref o, ref o);
			}
		}

		private void WebBrowserPrint()
		{
			ParentModule.Host.LogManager.WriteVerbose(this, "Print.", "WebBrowser");

			ExecCommandID(SHDocVw.OLECMDID.OLECMDID_PRINT);
		}

		private void WebBrowserPrintPreview()
		{
			ParentModule.Host.LogManager.WriteVerbose(this, "Print preview.", "WebBrowser");

			ExecCommandID(SHDocVw.OLECMDID.OLECMDID_PRINTPREVIEW);
		}

		private void WebBrowserPageSetup()
		{
			ParentModule.Host.LogManager.WriteVerbose(this, "Page setup.", "WebBrowser");

			ExecCommandID(SHDocVw.OLECMDID.OLECMDID_PAGESETUP);
		}

		private void WebBrowserOpenFile()
		{
			OpenFileDialog _openFileDialog = new OpenFileDialog();
			string openString = LocalizationExtender.GetString("OpenFileFilter");

			_openFileDialog.Filter = openString == null ? "txt files (*.txt)|*.txt|All files (*.*)|*.*" : openString;
			_openFileDialog.FilterIndex = 2;
			_openFileDialog.RestoreDirectory = true;

			if (_openFileDialog.ShowDialog() == DialogResult.OK)
			{
				cbAddress.Text = _openFileDialog.FileName;
				ParentModule.Host.LogManager.WriteVerbose(this, "Open file: " + _openFileDialog.FileName, "WebBrowser");

				WebBrowserGo();
			}
		}

		private void WebBrowserSaveFile()
		{
			ParentModule.Host.LogManager.WriteVerbose(this, "Save file.", "WebBrowser");

			ExecCommandID(SHDocVw.OLECMDID.OLECMDID_SAVEAS);
		}

		private void WebBrowserCopyClipboard()
		{
			ParentModule.Host.LogManager.WriteVerbose(this, "Copy to clipboard.", "WebBrowser");

			ExecCommandID(SHDocVw.OLECMDID.OLECMDID_COPY);
		}

		private void WebBrowserCutClipboard()
		{
			ParentModule.Host.LogManager.WriteVerbose(this, "Cut to clipboard.", "WebBrowser");

			ExecCommandID(SHDocVw.OLECMDID.OLECMDID_CUT);
		}

		private void WebBrowserPasteClipboard()
		{
			ParentModule.Host.LogManager.WriteVerbose(this, "Paste from clipboard.", "WebBrowser");

			ExecCommandID(SHDocVw.OLECMDID.OLECMDID_PASTE);
		}

		private void WebBrowserSelectAll()
		{
			ParentModule.Host.LogManager.WriteVerbose(this, "Select all.", "WebBrowser");

			ExecCommandID(SHDocVw.OLECMDID.OLECMDID_SELECTALL);
		}

		private void SetActiveWebBrowser()
		{
			TD.SandDock.TabbedDocument _TabPage;
			_TabPage = lastActivatedDocument;
			if (_TabPage == null)
			{
				WebBrowserNewTab();
				_TabPage = lastActivatedDocument;
			}
			for (int i = 0; i < _TabPage.Controls.Count; i++)
			{
				if (_TabPage.Controls[i].GetType().Name == "AxWebBrowser")
				{
					_ActiveWebBrowser = (AxSHDocVw.AxWebBrowser)_TabPage.Controls[i];
					HE_WebBrowserTag _HE_WebBrowserTag;

					_HE_WebBrowserTag = (HE_WebBrowserTag)_ActiveWebBrowser.Tag;
					_HE_WebBrowserTag._TabIndex = documentContainer.Controls.IndexOf(lastActivatedDocument);
					//toolStripStatusLabel.Text = _ActiveWebBrowser.LocationURL;
					_ActiveWebBrowser.RegisterAsBrowser = true;

					cbAddress.Text = _ActiveWebBrowser.LocationURL;
					if (cbAddress.Text == string.Empty)
					{
						cbAddress.Text = "about:blank";
					}
					tsbBack.Enabled = _HE_WebBrowserTag._CanBack;
					tsbForward.Enabled = _HE_WebBrowserTag._CanForward;
					break;
				}
			}
		}

		private AxSHDocVw.AxWebBrowser CreateNewWebBrowser()
		{
			return CreateNewWebBrowser("about:blank");
		}

		private AxSHDocVw.AxWebBrowser CreateNewWebBrowser(string url)
		{
			AxSHDocVw.AxWebBrowser _axWebBrowser = new AxSHDocVw.AxWebBrowser();
			_axWebBrowser.Tag = new HE_WebBrowserTag();
			TD.SandDock.TabbedDocument _TabPage = new TD.SandDock.TabbedDocument();
			_TabPage.BackColor = System.Drawing.SystemColors.Window;
			_TabPage.FloatingSize = new System.Drawing.Size(550, 400);
			_TabPage.Guid = new System.Guid("a391a42f-b7f0-4773-9d75-04f2c86636d9");
			_TabPage.Location = new System.Drawing.Point(1, 21);
			_TabPage.Name = "_tabPage";
			_TabPage.Padding = new System.Windows.Forms.Padding(8);
			_TabPage.Size = new System.Drawing.Size(433, 231);
			_TabPage.TabIndex = 0;
			_TabPage.Text = url;

			_axWebBrowser.Dock = DockStyle.Fill;
			_axWebBrowser.Margin = Padding.Empty;
			_axWebBrowser.Padding = Padding.Empty;
			_axWebBrowser.BeforeNavigate2 += new AxSHDocVw.DWebBrowserEvents2_BeforeNavigate2EventHandler(this.axWebBrowser_BeforeNavigate2);
			_axWebBrowser.CommandStateChange += new AxSHDocVw.DWebBrowserEvents2_CommandStateChangeEventHandler(this.axWebBrowser_CommandStateChange);
			_axWebBrowser.DocumentComplete += new AxSHDocVw.DWebBrowserEvents2_DocumentCompleteEventHandler(this.axWebBrowser_DocumentComplete);
			_axWebBrowser.NavigateComplete2 += new AxSHDocVw.DWebBrowserEvents2_NavigateComplete2EventHandler(this.axWebBrowser_NavigateComplete2);
			_axWebBrowser.NavigateError += new AxSHDocVw.DWebBrowserEvents2_NavigateErrorEventHandler(this.axWebBrowser_NavigateError);
			_axWebBrowser.NewWindow2 += new AxSHDocVw.DWebBrowserEvents2_NewWindow2EventHandler(this.axWebBrowser_NewWindow2);
			_axWebBrowser.ProgressChange += new AxSHDocVw.DWebBrowserEvents2_ProgressChangeEventHandler(this.axWebBrowser_ProgressChange);
			_axWebBrowser.StatusTextChange += new AxSHDocVw.DWebBrowserEvents2_StatusTextChangeEventHandler(this.axWebBrowser_StatusTextChange);
			_axWebBrowser.TitleChange += new AxSHDocVw.DWebBrowserEvents2_TitleChangeEventHandler(this.axWebBrowser_TitleChange);
			_axWebBrowser.WindowClosing += new AxSHDocVw.DWebBrowserEvents2_WindowClosingEventHandler(this.axWebBrowser_WindowClosing);
			Object o = null;

			_TabPage.Controls.Add(_axWebBrowser);
			//documentContainer.Controls.Add(_TabPage);
			_TabPage.Manager = sandDockManager;
			_TabPage.MaximumTabWidth = 200;
			_TabPage.Open(TD.SandDock.WindowOpenMethod.OnScreenActivate);
			//_TabPage.Activate();
			Application.DoEvents();
			_axWebBrowser.Navigate(url, ref o, ref o, ref o, ref o);
			documentContainer.ActiveControl = _TabPage;
			return _axWebBrowser;
		}

		private mshtml.HTMLDocument GetDocument()
		{
			try
			{
				mshtml.HTMLDocument htm = (mshtml.HTMLDocument)_ActiveWebBrowser.Document;
				return htm;
			}
			catch
			{
				ParentModule.Host.LogManager.WriteError(this, "Cannot retrieve the document from the WebBrowser control.", "WebBrowser");
				string errorString = LocalizationExtender.GetString("GetDocumentError");
				if (errorString == null)
				{
					errorString = "Cannot retrieve the document.";
				}
				string errorHeaderString = LocalizationExtender.GetString("GetDocumentErrorHeader");
				if (errorHeaderString == null)
				{
					errorHeaderString = "Error";
				}

				MessageBox.Show(errorString, errorHeaderString, MessageBoxButtons.OK, MessageBoxIcon.Error);
				return null;
			}
		}

		private void ExecCommandID(SHDocVw.OLECMDID _OLECMDID)
		{
			int response = (int)_ActiveWebBrowser.QueryStatusWB(_OLECMDID);
			bool IsOK = (response & (int)SHDocVw.OLECMDF.OLECMDF_ENABLED) != 0 ? true : false;
			if (IsOK == false)
			{
				ParentModule.Host.LogManager.WriteInfo(this, "ExecCommandID return false for " + _OLECMDID, "WebBrowser");

				return;
			}

			Object o = null;
			_ActiveWebBrowser.ExecWB(_OLECMDID, SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, ref o, ref o);
		}

		#endregion

		#region Favorites handling

		private void WebBrowserShowFavorites()
		{
			if (mFavoritesControl != null)
			{
				return;
			}

			mFavoritesControl = new FavoritesControl(mParentModule);
			mParentModule.Host.Smartparts.Add(mFavoritesControl);
			mFavoritesControl.OnFavoritesClicked += new FavoritesControl.FavoritesClickedHandler(mFavoritesControl_OnFavoritesClicked);
			mFavoritesControl.OnClosed += new EventHandler(mFavoritesControl_OnClosed);

			mFavoritesControl.IsVisible = true;
		}

		private void mFavoritesControl_OnClosed(object sender, EventArgs e)
		{
			mFavoritesControl.OnFavoritesClicked -= new FavoritesControl.FavoritesClickedHandler(mFavoritesControl_OnFavoritesClicked);
			mFavoritesControl.OnClosed -= new EventHandler(mFavoritesControl_OnClosed);
			mParentModule.Host.Smartparts.Remove(mFavoritesControl);
			mFavoritesControl.Dispose();
			mFavoritesControl = null;
		}

		private void mFavoritesControl_OnFavoritesClicked(FavoritesClickedEventArgs ea)
		{
			WebBrowserGo(ea.Url);
		}

		#endregion

		#region Private helper things

		private enum MiscCommandTarget
		{ Find = 1, ViewSource, Options }

		#endregion

		#region Helper things

		//Version 2.00

		//Include the following interface declaration just before your application's namespace
		//declaration to add a reference to the Microsoft HTML (MSHTML) IOleCommandTarget interface
		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
		public struct OLECMDTEXT
		{
			public uint cmdtextf;
			public uint cwActual;
			public uint cwBuf;
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
			public char rgwz;
		}

		[StructLayout(LayoutKind.Sequential)]
		public struct OLECMD
		{
			public uint cmdID;
			public uint cmdf;
		}

		// Interop definition for IOleCommandTarget.
		[ComImport,
		Guid("b722bccb-4e68-101b-a2bc-00aa00404770"),
		InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		public interface IOleCommandTarget
		{
			//IMPORTANT: The order of the methods is critical here. You
			//perform early binding in most cases, so the order of the methods
			//here MUST match the order of their vtable layout (which is determined
			//by their layout in IDL). The interop calls key off the vtable ordering,
			//not the symbolic names. Therefore, if you switched these method declarations
			//and tried to call the Exec method on an IOleCommandTarget interface from your
			//application, it would translate into a call to the QueryStatus method instead.
			void QueryStatus(ref Guid pguidCmdGroup, UInt32 cCmds,
				[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] OLECMD[] prgCmds, ref OLECMDTEXT CmdText);
			void Exec(ref Guid pguidCmdGroup, uint nCmdId, uint nCmdExecOpt, ref object pvaIn, ref object pvaOut);
		}

		//Each instance of a web browser will have in its tag an HE_WebBrowserTag object
		//that holds some details on that web browser object
		public class HE_WebBrowserTag
		{
			public int _TabIndex = 0;
			public bool _CanBack = false;
			public bool _CanForward = false;
		}

		#endregion
	}
}
